package com.foreverwin.jzymes.production.debur.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.domain.NcData;
import com.foreverwin.jzymes.common.enums.DispositionEnum;
import com.foreverwin.jzymes.common.mapper.NcDataMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.common.util.CommonMethods;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.event.AppEventPublisher;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import com.foreverwin.jzymes.framework.util.ObjectMapperUtil;
import com.foreverwin.jzymes.production.debur.service.IDeburNCRecordAdviceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class DeburNCRecordAdviceServiceImpl implements IDeburNCRecordAdviceService {
    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    IItemAdviceService itemAdviceService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    INCCodeAdviceService ncCodeAdviceService;
    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    NcDataMapper ncDataMapper;
    @Autowired
    AppEventPublisher appEventPublisher;

    /**
     * 去毛刺不良录入
     *
     * @param jsonMap
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void recordDeburNC( Map<String,Object> jsonMap ){

        /**检查不良录入字段*/
        checkFieldsForRecordNC( jsonMap );

        /**检查不良明细*/
        List<Map<String,Object>> ncList = (List<Map<String, Object>>) jsonMap.get( "ncList" );
        Assert.isTrue( ncList != null && ncList.size() > 0, I18nUtil.getI18nText( "production.nc.ncListNotNull" ) );

        /**添加公用字段*/
        jsonMap.remove( "ncList" );
        Date createdDateTime = new Date();
        //List<String> ncCodeList = new ArrayList<>();
        for( Map<String,Object> map : ncList ){
            map.putAll( jsonMap );

            /**检查不合格代码*/
            ncCodeAdviceService.existNCCode( (String)map.get("site"), (String)map.get("ncCode") );

            /*if( ncCodeList.contains( map.get("ncCode") ) ){
                throw BusinessException.build( "production.debur.ncCodeDuplicate", new String[]{ (String)map.get("ncCode") } );
            }
            ncCodeList.add( (String)map.get("ncCode") );*/

            if( map.containsKey( "scrapQty" ) && StringUtils.isNotBlank( (String)map.get( "scrapQty" ) ) ){
                saveScrapNcData( map, createdDateTime );

                JSONObject eventData = new JSONObject();
                eventData.put( "SITE", map.get( "site" ) );
                eventData.put( "ITEM_BO", map.get( "itemBo" ) );
                eventData.put( "RESRCE", map.get( "resrce" ) );
                eventData.put( "QTY", Long.valueOf( (String)map.get( "scrapQty" ) ) );
                AppEvent<JSONObject> appEvent = new AppEvent<>( this );
                appEvent.setName( "ITEM_NC_SCRAP_EVENT" );
                appEvent.setData( eventData );
                appEventPublisher.publishEvent( appEvent );
            }
            if( map.containsKey( "reworkQty" ) && StringUtils.isNotBlank( (String)map.get( "reworkQty" ) ) ){
                saveReworkNcData( map, createdDateTime );

                JSONObject eventData = new JSONObject();
                eventData.put( "SITE", map.get( "site" ) );
                eventData.put( "ITEM_BO", map.get( "itemBo" ) );
                eventData.put( "RESRCE", map.get( "resrce" ) );
                eventData.put( "QTY", Long.valueOf( (String)map.get( "reworkQty" ) ) );
                AppEvent<JSONObject> appEvent = new AppEvent<>( this );
                appEvent.setName( "ITEM_NC_REWORK_EVENT" );
                appEvent.setData( eventData );
                appEventPublisher.publishEvent( appEvent );
            }
        }
    }

    /**
     * 保存不可返工数量
     *
     * @param map
     * @param createdDateTime
     */
    public void saveScrapNcData( Map<String,Object> map, Date createdDateTime ){
        Long scrapQty = Long.valueOf( (String)map.get( "scrapQty" ) );
        if( scrapQty > 0 ){
            NcData ncData = ObjectMapperUtil.convertValue( map, NcData.class );
            ncData.setNcQty( scrapQty );
            ncData.setDisposition( DispositionEnum.SCRAP.getValue() );
            ncData.setCnc( findDateCodeCnc( ncData.getSite(), ncData.getDateCode() ) );
            ncData.setCreatedDateTime( createdDateTime );
            ncData.setCreateUserBo( CommonMethods.getUserBo() );
            commonService.saveNcData( ncData, false );
        }
    }

    /**
     * 保存可返工数量
     *
     * @param map
     * @param createdDateTime
     */
    public void saveReworkNcData( Map<String,Object> map, Date createdDateTime ){
        Long reworkQty = Long.valueOf( (String)map.get( "reworkQty" ) );
        if( reworkQty > 0 ){
            NcData ncData = ObjectMapperUtil.convertValue( map, NcData.class );
            ncData.setNcQty( reworkQty );
            ncData.setDisposition( DispositionEnum.OK.getValue() );
            ncData.setIsRework( "true" );
            ncData.setCnc( findDateCodeCnc( ncData.getSite(), ncData.getDateCode() ) );
            ncData.setCreatedDateTime( createdDateTime );
            ncData.setCreateUserBo( CommonMethods.getUserBo() );
            ncData.setHandle( BOHandleUtil.buildNCDataHandle() );
            ncDataMapper.insertNcData( ncData );
        }
    }

    /**
     * 查找dateCode对应机台
     *
     * @param site
     * @param dateCode
     * @return
     */
    public String findDateCodeCnc( String site, String dateCode ){
        /**dateCode截取开始位置*/
        int startIndex = Integer.valueOf( systemRuleAdviceService.existSystemRule( site, Constants.SYSTEM_RULE_DATE_CODE_START_INDEX ) );
        /**dateCode截取结束位置*/
        int endIndex = Integer.valueOf( systemRuleAdviceService.existSystemRule( site, Constants.SYSTEM_RULE_DATE_CODE_END_INDEX ) );
        String customValue = StringUtils.substring( dateCode, startIndex, endIndex );
        Assert.hasText( customValue, I18nUtil.getI18nText( "production.nc.dateCodeNotValid", new String[]{ dateCode } ) );
        String resourceHandle = customFieldsAdviceService.findCustomFieldHandle( site, Constants.RESRCE_CUSTOM_FIELD_DATECODE, customValue );
        Assert.hasText( resourceHandle, I18nUtil.getI18nText( "production.nc..resourceOnDateCodeNotExist", new String[]{ dateCode } ) );
        return BOHandleUtil.splitResourceHandle( resourceHandle )[1];
    }


    /**
     * 检查不良录入字段
     *
     * @param headMap
     */
    public void checkFieldsForRecordNC( Map<String,Object> headMap ){
        /**检查站点*/
        siteAdviceService.existSite((String) headMap.get( "site" ));
        /**查询机种*/
        String itemGroup = itemGroupAdviceService.findItemGroupBySite( (String) headMap.get( "site" ) );
        headMap.put( "machineType", itemGroup );
        /**检查设备*/
        Map<String,Object> resourceMap = resourceAdviceService.existResource( (String) headMap.get( "site" ), (String) headMap.get( "resrce" ));
        /**检查工序*/
        String operation = resourceAdviceService.findOperationByResource( resourceMap );
        headMap.put( "operation", operation );
        /**检查物料*/
        itemAdviceService.existItem( (String) headMap.get( "itemBo" ) );
        /**检查DateCode*/
        Assert.hasText( (String) headMap.get("dateCode"), I18nUtil.getI18nText("production.nc.dateCodeNotValid", new Object[]{ headMap.get("dateCode") } ));
    }
}
